<template>
    <div class="channel-config">
        <!-- 顶部 -->
        <div class="toolbar">
            <span class="label">配置应用频道：</span>
            <a-button size="small" @click="onCreate">新增</a-button>
        </div>

        <!-- 表格 -->
        <a-table :columns="columns" :data-source="pagedData" row-key="rowKey" size="small" bordered :pagination="false"
            class="table" :scroll="{ x: 'max-content' }" @change="onTableChange">
            <template #bodyCell="{ column, record, index }">
                <!-- 序号 -->
                <template v-if="column.dataIndex === 'order'">
                    {{ (page - 1) * pageSize + index + 1 }}
                </template>

                <!-- 展示名称 -->
                <template v-else-if="column.dataIndex === 'displayName'">
                    <a-input v-model:value="record.displayName" size="small" :maxlength="50" allow-clear @keyup.stop
                        @keydown.stop @pressEnter="onDisplayNameBlur(record)" @blur="onDisplayNameBlur(record)"
                        placeholder="请输入展示名称" style="width: 100%; min-width: 160px" />
                </template>

                <!-- 是否显示 -->
                <template v-else-if="column.dataIndex === 'visible'">
                    {{ record.visible ? '是' : '否' }}
                </template>

                <!-- 操作 -->
                <template v-else-if="column.key === 'action'">
                    <a-button type="link" size="small" @click="moveUp(record)" :disabled="isFirst(record)">上移</a-button>
                    <span class="sep">|</span>
                    <a-button type="link" size="small" @click="moveDown(record)"
                        :disabled="isLast(record)">下移</a-button>
                </template>
            </template>
        </a-table>

        <!-- 底部 -->
        <div class="pager-bar">
            <div class="total">本页 {{ pagedData.length }} 条，共 {{ data.length }} 条。</div>
            <div class="pager-right">
                <a-pagination :current="page" :page-size="pageSize" :total="data.length" :show-less-items="true"
                    @change="onPageChange" />
                <a-select v-model:value="pageSize" size="small" :options="pageSizeOptions" class="page-size-select"
                    @change="onPageSizeChange" />
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref, watch, defineExpose } from 'vue'
import { message } from 'ant-design-vue'
import type { TableColumnType } from 'ant-design-vue'
import api from '@/api/api'

const props = defineProps<{
    /** 第3步是否激活 */
    active: boolean
    /** 第2步选择的频道ID */
    selectedIds?: Array<number | string>
    /** 应用ID */
    appId?: string | number
    /** 编辑回显 */
    initialRows?: Array<{
        rowKey: number | string
        id: number | string
        name: string
        displayName: string
        visible: boolean
        channelId?: string | number
        appId?: string | number
    }>
}>()

/** 表格行结构 */
type Row = {
    rowKey: number | string
    id: string | number
    channelId: string | number
    appId?: string | number
    name: string
    displayName: string
    visible: boolean
}

const data = reactive<Row[]>([])

/** 已加载 */
const hasLoaded = ref(false)
const hasDirty = ref(false)

function idsToStr(ids?: Array<number | string>) {
    return Array.isArray(ids) ? ids.join(',') : ''
}
const lastIdsStr = ref('')
const lastAppId = ref<string | number | undefined>(undefined)


function mapItemToRow(it: any, idx: number): Row {
    const channelId = it.channel_id ?? it.id ?? it.app_channel_id ?? String(idx)
    const appId = it.app_id ?? it.appId
    const name = it.channel_name ?? ''
    const displayName = it.channel_show_name ?? name
    const visible = String(it.channel_show ?? 'true') !== 'false'
    return {
        rowKey: channelId,
        id: channelId,
        channelId,
        appId,
        name,
        displayName,
        visible
    }
}


function mergeInitialRows(rows: Row[]) {
    const ir = props.initialRows || []
    if (!ir.length) return rows

    const initMap = new Map<string | number, any>()
    ir.forEach(r => {
        const key = r.channelId ?? r.id
        if (key != null) initMap.set(key, r)
    })

    return rows.map(r => {
        const found = initMap.get(r.channelId)
        if (!found) return r
        return {
            ...r,
            displayName: (found.displayName ?? '').toString().trim() || r.displayName || r.name,
            visible: typeof found.visible === 'boolean' ? found.visible : r.visible
        }
    })
}

/** 拉接口并填充数据 */
async function fetchAndFillByIds(ids?: Array<number | string>) {
    try {
        const params: any = {}
        if (props.appId !== undefined && props.appId !== null) params.app_id = props.appId
        if (ids && ids.length) params.ids = ids.join(',')

        const res: any = await api.searchAppChannelList(params)
        const list: any[] = (res && res.data) || []

        const idSet = new Set(ids || [])
        let rows: Row[] =
            (ids && ids.length
                ? list.filter((it: any) => {
                    const anyId = it.id ?? it.channel_id ?? it.app_channel_id
                    return idSet.has(anyId)
                })
                : list
            ).map(mapItemToRow)

        rows = mergeInitialRows(rows)

        data.splice(0, data.length, ...rows)
        lastIdsStr.value = idsToStr(ids)
        lastAppId.value = props.appId
        hasLoaded.value = true
        hasDirty.value = false
    } catch (e: any) {
        message.error(e?.message || '频道配置加载失败')
    }
}

/** 初次激活 */
watch(
    () => props.active,
    async (on) => {
        if (!on) return
        const idsStr = idsToStr(props.selectedIds)
        const appId = props.appId
        const needFetch = !hasLoaded.value || idsStr !== lastIdsStr.value || appId !== lastAppId.value

        if (needFetch && props.selectedIds && props.selectedIds.length) {
            await fetchAndFillByIds(props.selectedIds)
            return
        }

        if (!hasLoaded.value && (!props.selectedIds || props.selectedIds.length === 0)) {
            const ir = props.initialRows || []
            if (ir.length) {
                const rows = ir.map((r, idx) => ({
                    rowKey: r.channelId ?? r.id ?? idx,
                    id: r.channelId ?? r.id ?? idx,
                    channelId: r.channelId ?? r.id ?? idx,
                    appId: r.appId,
                    name: r.name,
                    displayName: (r.displayName ?? '').toString().trim() || r.name,
                    visible: !!r.visible
                }))
                data.splice(0, data.length, ...rows)
                lastIdsStr.value = ''
                lastAppId.value = props.appId
                hasLoaded.value = true
                hasDirty.value = true
            }
        }
    },
    { immediate: true }
)

/** 激活态下，确实发生的时候变更时才覆盖 */
watch(
    () => idsToStr(props.selectedIds),
    async (cur, prev) => {
        if (!props.active) return
        if (cur !== prev) await fetchAndFillByIds(props.selectedIds)
    }
)
watch(
    () => props.appId,
    async (cur, prev) => {
        if (!props.active) return
        if (cur !== prev) await fetchAndFillByIds(props.selectedIds)
    }
)

/** 排序/分页/列 */
const sorterState = ref<{ field?: string; order?: 'ascend' | 'descend' | null }>({})
const page = ref(1)
const pageSize = ref(10)
const pageSizeOptions = [
    { label: '10条/页', value: 10 },
    { label: '20条/页', value: 20 },
    { label: '50条/页', value: 50 }
]

const columns = ref<TableColumnType<Row>[]>([
    { title: '显示顺序', dataIndex: 'order', width: 110, align: 'center' },
    { title: '频道名称', dataIndex: 'name', width: 130 },
    { title: '展示名称', dataIndex: 'displayName', width: 200 }, // 可编辑列
    { title: '是否显示', dataIndex: 'visible', width: 120, sorter: (a, b) => Number(a.visible) - Number(b.visible) },
    { title: '操作', key: 'action', width: 160 }
])

const sortedData = computed(() => {
    const { field, order } = sorterState.value
    if (!field || !order) return data
    const list = [...data]
    list.sort((a: any, b: any) => {
        const va = a[field]; const vb = b[field]
        if (va === vb) return 0
        const r = String(va).localeCompare(String(vb))
        return order === 'ascend' ? r : -r
    })
    return list
})

const pagedData = computed(() => {
    const start = (page.value - 1) * pageSize.value
    return sortedData.value.slice(start, start + pageSize.value)
})

/** 失焦时清理并标记为脏 */
function onDisplayNameBlur(row: Row) {
    const v = (row.displayName ?? '').toString().trim()
    row.displayName = v || row.name
    hasDirty.value = true
}

function indexInData(row: Row) { return data.findIndex(d => d.rowKey === row.rowKey) }
function isFirst(row: Row) { return indexInData(row) === 0 }
function isLast(row: Row) { return indexInData(row) === data.length - 1 }
function moveUp(row: Row) { const i = indexInData(row); if (i > 0) [data[i - 1], data[i]] = [data[i], data[i - 1]]; hasDirty.value = true }
function moveDown(row: Row) { const i = indexInData(row); if (i >= 0 && i < data.length - 1) [data[i], data[i + 1]] = [data[i + 1], data[i]]; hasDirty.value = true }
function onTableChange(_: any, __: any, sorter: any) { sorterState.value = { field: sorter?.field, order: sorter?.order } }
function onCreate() { }
function onPageChange(p: number) { page.value = p }
function onPageSizeChange() { page.value = 1 }

/** 暴露所有行 */
function getAllRows() { return [...data] }
defineExpose({ getAllRows })
</script>

<style scoped lang="less">
.channel-config {
    width: 100%;
}

/* 顶部栏 */
.toolbar {
    display: flex;
    align-items: center;
    margin-bottom: 8px;

    .label {
        margin-right: 8px;
        font-size: 14px;
    }
}

.table {
    :deep(.ant-table) {
        font-size: 13px;
    }

    :deep(.ant-table-thead > tr > th),
    :deep(.ant-table-tbody > tr > td) {
        padding: 8px 12px;
    }

    :deep(.ant-table-thead > tr > th) {
        background: #F4F8FD !important;
    }

    .sep {
        color: #c3c3c3;
        margin: 0 2px;
    }
}

.pager-bar {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 12px;
    margin-top: 10px;

    .total {
        color: #333;
        font-size: 14px;
        padding-left: 4px;
    }

    .pager-right {
        display: inline-flex;
        align-items: center;
        gap: 12px;
    }

    .page-size-select {
        width: 92px;
    }
}
</style>
